#  -*- coding:utf-8 -*- 
"""
@ author: 罗金盛
@ time: 2024/5/27 
@ file: report_information.py

"""
from datetime import datetime
import logging
from DrissionPage import WebPage
from DrissionPage.common import Actions
from src.db.crud import ReportDetails
from src.config import LoggerConfig, Config
from DrissionPage.errors import ElementNotFoundError
from DrissionPage.common import Settings
from src.spider.auto_login import AuditLogin
from src.utils import download_file, ReportFetcher
from src.spider.upload_file import PDFUploader
from src.spider.feishu_document import append_to_sheet

Settings.raise_when_ele_not_found = True

# 配置日志
LoggerConfig.configure_logger('log/sn-audit-report.log')


class ReportInformation:
    def __init__(self):
        """
        初始化 ReportInformation 类，创建 WebPage 和 Actions 实例，并设置 ReportDetails 实例
        """
        try:
            self.page = WebPage('d')
            self.ac = Actions(self.page)
            self.report_details = ReportDetails()
            self.logging = logging.getLogger('ReportInformation')
            self.config = Config()

            # 有关飞书云文档的配置项
            self.app_id = self.config.feishu_document()['app_id']
            self.app_secret = self.config.feishu_document()['app_secret']
            self.spreadsheet_token = self.config.feishu_document()['spreadsheet_token']
            self.sheet_id = self.config.feishu_document()['sheet_id']

        except Exception as e:
            self.logging.error(f"初始化 ReportInformation 时发生错误: {e}", exc_info=True)

    def get_login_status(self):
        """
        获取登录状态 如果是登录的 直接进行信息填入 未登录则进行自动化登录
        """
        url = "http://acc.mof.gov.cn/login_achieve/login"
        self.page.get(url)
        try:
            ele = self.page('.welcome')
            if ele:
                self.process_report_details()
            else:
                self.login_and_process()
        except ElementNotFoundError:
            self.logging.info('登录状态：未登录，需要登录！')
            self.login_and_process()

    def login_and_process(self):
        """
        处理登录并获取报告详情
        """
        try:
            auto_login = AuditLogin()
            auto_login.get_login_status()
            self.process_report_details()
        except Exception as e:
            self.logging.error(f"自动化登录时发生错误: {e}", exc_info=True)

    def process_report_details(self):
        """
        处理报告详情
        """
        details = self.fetch_report_details()
        for detail in details:
            try:
                self.fill_report_details(detail)
                self.logging.info(f"报告详情已填写：{detail['报告文号']}")
                self.page.wait(60)  # 这里等待的目的是为了防止监管平台的数据延迟无法获取

                # 开始获取已赋码的报告文号对应的报告编码
                fetcher = ReportFetcher()
                file_no_to_search = detail['报告文号']
                back_number, index = fetcher.get_backnumber(file_no=file_no_to_search)

                if back_number:
                    self.report_details.update_c02_report(
                        new_c02ORNumber=back_number,
                        new_c02BBState='已报备获编号',
                        target_c02ReportNumber=file_no_to_search,
                        update_log_flag=True
                    )
                    save_path = self.config.file_adr()
                    self.fetch_report(index=index, rename=detail['报告编号']+'_ro2', save_path=save_path)

                    pdf_path = self.config.file_adr()+detail['报告编号']+'_ro2'+'.pdf'
                    upload_url = 'https://i-dev.sinongcpa.cn/cpscm/C22/Sign'
                    cookies = {
                        '.ASPXAUTH': 'F08DBA88E7F818175B89DAB7AE937B161DF823F5AE4122B5951C3B5F51A5EF6F17D3AC369B413D8D0349909DF470E6DDD8FE1049D8A0AAA2A5E264C41621069F1B214A962BA17E9D536AFE289BE4E1ED142449CCF93E5B6547F08D7D82F8C915335D3A46721843FFA8D0395DB86D6A478312379538B55B9695524B06F0B84C07A24B17B4E700D4357C48261E4394050144BDC9277865C802A1DD14FE87D7D05F7F6B35EA5E7D658A6B725057F94FA81630A2FEE2E3B4F4D11E838B10FBEC06EB9ED34E3B5E950A250E183D8FF7C7FAF017186527BF07803A108BC198B532EC1EC4F85A8B5A0AE12D7B234295FFD2D9022F718AEA9DC173BD5BDF0947589690D33715151DA6F48716D4D1934F56D26A7A95823DAB1F5DB1F01AB98612F3A247468ABD3DFDF27E8032E77117F395DBC294',
                        'ASP.NET_SessionId': 'dnaixqr3i3xenta0ecjik0hq',
                    }
                    data = {
                        'Id': str(detail['报告Id']),
                        'sObj': '注册会计师行业统一监管平台',
                        'sRNumber': str(back_number),
                        'Flag': 'false'
                    }

                    uploader = PDFUploader(pdf_path, upload_url, cookies, data)
                    try:
                        uploader.pdf_to_binary()
                        uploader.upload_pdf()
                    except Exception as e:
                        self.logging.error(f"处理上传司农平台pdf文件时出现异常: {e}", exc_info=True)

                    # 处理飞书云文档
                    OPNumber = detail['报告编号']
                    CusName = detail['被审计单位名称']
                    ReportNumber = detail['报告文号']
                    create_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                    status = '所有自动化流程运行正常'

                    response = append_to_sheet(self.app_id, self.app_secret, self.spreadsheet_token, self.sheet_id, OPNumber, CusName,
                                               ReportNumber, create_time,status)
                    print(response.get("msg"))

                else:
                    self.report_details.update_c02_report(
                        new_c02ORNumber='平台延迟或者报告已重复，无法获取对应编号',
                        new_c02BBState='数据齐可报备',
                        target_c02ReportNumber=file_no_to_search,
                        update_log_flag=False
                    )
                    OPNumber = detail['报告编号']
                    CusName = detail['被审计单位名称']
                    ReportNumber = detail['报告文号']
                    create_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                    status = '平台延迟或者报告已重复，无法获取对应编号'

                    response = append_to_sheet(self.app_id, self.app_secret, self.spreadsheet_token, self.sheet_id,
                                               OPNumber, CusName,
                                               ReportNumber, create_time, status)
                    print(response.get("msg"))
            except Exception as e:
                self.logging.error(f"处理 detail {detail} 时出现异常: {e}", exc_info=True)

    def fetch_report_details(self):
        """
        获取报告详细信息
        :return: 详细信息列表
        """
        try:
            details = self.report_details.get_detailinfo()
            return details
        except Exception as e:
            self.logging.error(f"获取报告详细信息时发生错误: {e}", exc_info=True)
            return []

    def fill_report_details(self, detail):
        """
        根据报告详细信息填写表单
        :param detail: 详细信息字典
        """
        try:
            self.logging.info(f"开始处理报告详细信息: {detail}")
            ReportId = detail['报告id']
            OPNumber = detail['报告编号']
            ReportName = detail['报告类型']
            CusName = detail['被审计单位名称']
            ReportNumber = detail['报告文号']
            audit_opinion = detail['审计意见类型']
            StartDate = detail['报告开始日期']
            EndDate = detail['报告结束日期']
            ReportDate = detail['报告日期']
            LicenceNum = detail['统一社会信用代码']
            chargeSum = detail['审计收费']
            assets = detail['资产信息']['资产总额(元)-审计后']
            liability = detail['资产信息']['负债总额(元)-审计后']
            profit = detail['资产信息']['利润总额(元)-审计后']
            revenue = detail['资产信息']['营业收入(元)-审计后']
            securities_business = detail['资产信息']['是否属于证券业务']
            Signatory_1 = detail['签字注册会计师'][0]
            Signatory_2 = detail['签字注册会计师'][1]
            RegAddress = detail['公司注册地和业务所在地']
            FilePath = detail['审计报告文件名称']

            url = "http://acc.mof.gov.cn/home/"
            self.page.get(url)

            self.page('@text():验证码信息报备').click(by_js=True)
            self.page.wait.eles_loaded('#vp')
            self.page('xpath://*[@id="app"]/section/main/div/div/div/div[1]/div[1]/div/div/div[1]/button').click(by_js=True)
            self.page.wait(1)

            CPA = self.config.CPA()
            leixing = CPA.get(ReportName, None)
            if leixing is None:
                self.report_details.update_c02_report(
                    new_c02ORNumber='无法确定具体业务类型，请手工录入数据！',
                    new_c02BBState='数据齐可报备',
                    target_c02ReportNumber=ReportNumber,
                    update_log_flag=False
                )
                OPNumber = detail['报告编号']
                CusName = detail['被审计单位名称']
                ReportNumber = detail['报告文号']
                create_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                status = '无法确定具体业务类型，请手工录入数据！'

                response = append_to_sheet(self.app_id, self.app_secret, self.spreadsheet_token, self.sheet_id,
                                           OPNumber, CusName,
                                           ReportNumber, create_time, status)
                print(response.get("msg"))
                self.logging.error(f"无法确定具体业务类型，请手工录入数据！", exc_info=True)

            else:
                business_type = self.page('.ant-select-selection__rendered', index=2)

                # 选择业务类型
                self.select_business_type(business_type, leixing)

                self.page('@text():确 定').click(by_js=True)
                self.page.wait(1)

                # 填写-被审计单位名称
                self.page('xpath://*[@id="clientName"]/div/div/ul/li/div/input').input(CusName + '\n')
                # 填写-统一社会信用代码
                self.page('xpath: //*[@id="clientCode"]').input(LicenceNum + '\n')
                self.page.wait(1)

                # 填写报告日期
                start = self.page('.ant-calendar-picker-input ant-input', index=1)
                self.ac.move_to(start, duration=0.5).click().wait(1).type(StartDate).wait(1).key_down('Enter').key_up('Enter')
                self.page.wait(1)
                end = self.page('.ant-calendar-picker-input ant-input', index=2)
                self.ac.move_to(end, duration=0.5).click().wait(1).type(EndDate).wait(1).key_down('Enter').key_up('Enter')

                # 填写报告文号和签名注册会计师
                self.page('xpath://*[@id="fileNo"]').input(ReportNumber)
                cpaName1 = self.page('.ant-select-selection__placeholder', index=1)
                self.ac.move_to(cpaName1).click().wait(0.5).type(Signatory_1).wait(2).key_down('down').key_up('down').wait(
                    0.5).key_down('Enter').key_up('Enter')

                self.page('.ant-select-selection__placeholder', index=2).click()
                cpaName2 = self.page('.ant-select-selection__placeholder', index=2)
                self.ac.move_to(cpaName2).click().wait(0.5).type(Signatory_2).wait(2).key_down('down').key_up('down').wait(
                    0.5).key_down('Enter').key_up('Enter')

                # 填充资产信息
                self.ac.move_to(self.page('xpath://*[@id="assets"]')).click().input(assets + '\n')
                self.ac.move_to(self.page('xpath://*[@id="liability"]')).click().input(liability + '\n')
                self.ac.move_to(self.page('xpath://*[@id="revenue"]')).click().input(revenue + '\n')
                self.ac.move_to(self.page('xpath://*[@id="profit"]')).click().input(profit + '\n')
                self.ac.move_to(self.page('xpath://*[@id="chargeSum"]')).click().input(chargeSum + '\n')

                # 填充公司注册地和业务所在地
                self.page('xpath://*[@id="clientDivision"]/div/div ').input(RegAddress + '\n')
                self.page('xpath://*[@id="busiDivision"]/div/div').input(RegAddress + '\n')

                # 填写是否属于证券业务
                if securities_business == '是':
                    self.ac.move_to(self.page('xpath://*[@id="isSfqBus"]/div/span')).click().key_down('up').key_up('up').key_down('Enter').key_up('Enter')

                self.page.wait(2)

                # 调用下载所需的pdf文件
                download_file(c02Code=OPNumber, fileName=FilePath,
                              save_path=self.config.file_adr())

                reportFile = self.page('xpath://*[@id="reportFile"]/span/div/span/button')
                # 文件上传 这个地方要采用绝对路径传
                reportFile.click.to_upload(self.config.file_adr() + FilePath)
                self.page.wait(10)

                # 填入报告日期
                reportDate = self.page('xpath://*[@id="reportDate"]/div/input')
                self.ac.move_to(reportDate, duration=0.5).click().wait(1).type(ReportDate).wait(1).key_down(
                    'Enter').key_up(
                    'Enter')
                self.page.wait(2)

                self.page('xpath://*[@id="app"]/section/div/div/div/button[3]').click(by_js=True)
                self.page.wait(2)

        except Exception as e:
            self.report_details.update_c02_report(
                new_c02ORNumber='填充报告信息时发生错误，请手工录入数据！',
                new_c02BBState='数据齐可报备',
                target_c02ReportNumber=detail['报告文号'],
                update_log_flag=False
            )
            OPNumber = detail['报告编号']
            CusName = detail['被审计单位名称']
            ReportNumber = detail['报告文号']
            create_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            status = '填充报告信息时发生错误，请手工录入数据！'

            response = append_to_sheet(self.app_id, self.app_secret, self.spreadsheet_token, self.sheet_id,
                                       OPNumber, CusName,
                                       ReportNumber, create_time, status)
            print(response.get("msg"))
            self.logging.error(f"填充报告信息时发生错误: {e}", exc_info=True)

    def fetch_report(self,index, rename, save_path):
        try:
            # 打开URL
            url = "http://acc.mof.gov.cn/home/"
            self.page.get(url)

            # 点击验证码信息报备
            self.page('@text():验证码信息报备').click(by_js=True)
            self.page.wait.eles_loaded('#vp')

            # 点击已赋码
            self.page('@text()=已赋码').click(by_js=True)

            # 移动到指定索引位置进行双击
            ele = self.page('.ant-tabs-tab-active ant-tabs-tab')  # 注意选择器中的空格需要替换为点号
            self.ac.move_to(ele).move(offset_y=120 + index * 32).wait(0.5).db_click()

            # 等待加载
            self.page.wait(5)

            # 下载文件
            file = self.page('xpath://*[@id="reportFile"]/div/div/div/div[2]/div/button[2]')
            self.page.set.when_download_file_exists('overwrite')    # 设置同名文件覆盖
            file_stream = file.click.to_download(save_path=save_path, rename=rename, by_js=True)
            file_stream.wait()    # 关键点在于这个地方的保存等待 不然无法转为正常的pdf文件
            self.logging.info(f"文件下载完成: {save_path}")

        except Exception as e:
            self.logging.error(f"下载过程中发生错误: {e}", exc_info=True)


    def select_business_type(self, business_type_element, leixing):
        """
        根据业务类型选择对应的选项
        :param business_type_element: 业务类型选择元素
        :param leixing: 业务类型
        """
        self.ac.move_to(business_type_element).click()

        if leixing == '上市公司审计':
            self.ac.move(offset_y=50).click()
        elif leixing == '国有大型企业审计':
            self.ac.move(offset_y=80).click()
        elif leixing == '新三板企业审计':
            self.ac.move(offset_y=100).click()
        elif leixing == '一般企业审计':
            self.ac.move(offset_y=50).scroll(delta_y=100).move(offset_y=30).click()
        elif leixing == '事业单位审计':
            self.ac.move(offset_y=50).scroll(delta_y=100).move(offset_y=60).click()
        elif leixing == '民间非盈利组织等其他单位审计':
            self.ac.move(offset_y=50).scroll(delta_y=100).move(offset_y=90).click()
        elif leixing == '内控审计报告':
            self.ac.move(offset_y=50).scroll(delta_y=100).move(offset_y=120).click()
        elif leixing == '内控鉴证报告':
            self.ac.move(offset_y=50).scroll(delta_y=100).move(offset_y=150).click()
        elif leixing == '验资业务':
            self.ac.move(offset_y=50).scroll(delta_y=100).move(offset_y=180).click()
        elif leixing == '专项审计业务':
            self.ac.move(offset_y=50).scroll(delta_y=100).move(offset_y=220).click()
        elif leixing == '其他报告':
            self.ac.move(offset_y=50).scroll(delta_y=100).move(offset_y=250).click()



